use anyhow::Result;
use std::collections::HashMap;
use std::sync::atomic::AtomicI64;
use std::sync::atomic::Ordering::Relaxed;
use std::sync::Arc;

#[derive(Debug)]
pub struct AmapMetrics {
    data: Arc<HashMap<&'static str, AtomicI64>>,
}

impl Clone for AmapMetrics {
    fn clone(&self) -> Self {
        AmapMetrics {
            data: Arc::clone(&self.data),
        }
    }
}

impl AmapMetrics {
    pub fn new(metric_names: &[&'static str]) -> AmapMetrics {
        let map = metric_names
            .iter()
            .map(|&s| (s, AtomicI64::new(0)))
            .collect();
        AmapMetrics {
            data: Arc::new(map),
        }
    }

    #[allow(dead_code)]
    pub fn inc(&self, key: &str) -> Result<()> {
        let counter = self
            .data
            .get(key)
            .ok_or_else(|| anyhow::Error::msg(format!("key {key} not found")))?;
        counter.fetch_add(1, Relaxed);
        Ok(())
    }

    #[allow(dead_code)]
    pub fn des(&self, key: &str) -> Result<()> {
        let counter = self
            .data
            .get(key)
            .ok_or_else(|| anyhow::Error::msg(format!("key {key} not found")))?;
        counter.fetch_min(1, Relaxed);
        Ok(())
    }
}
